package logurs

import (
	"fmt"
	"os"
	"path/filepath"

	"gopkg.in/natefinch/lumberjack.v2"

	"github.com/sirupsen/logrus"
)

type RotateHook struct {
	levelOutputs []*lumberjack.Logger
}

func NewRotateHook(opts ...Option) *RotateHook {
	hook := &RotateHook{
		levelOutputs: make([]*lumberjack.Logger, len(logrus.AllLevels)),
	}
	//为每个等级各创建一个切割器
	for i, level := range logrus.AllLevels {
		output := &lumberjack.Logger{
			// 日志输出文件路径，默认os.TempDir()
			Filename: os.TempDir(),
			// 日志文件最大 size, 单位是 MB，默认100MB
			//MaxSize: 100,
			// 保留过期文件的最大时间间隔,单位是天，默认不过期
			//MaxAge: 0,
			// 最大过期日志保留的个数，默认全部保留，若设置了MaxAge，优先以MaxAge为准
			//MaxBackups: 0,
			// 是否需要压缩滚动日志, 使用的 gzip 压缩，默认不压缩
			//Compress: false,
			// 是否使用时间戳命名 backup 日志, 默认使用 UTC 格式，默认不启用
			//LocalTime: false,
		}
		for _, opt := range opts {
			opt(output)
		}
		output.Filename = levelName(output.Filename, level.String())
		hook.levelOutputs[i] = output
	}
	return hook
}

func (hook *RotateHook) Levels() []logrus.Level {
	return logrus.AllLevels
}

func (hook *RotateHook) Fire(entry *logrus.Entry) error {
	line, err := entry.String()
	if err != nil {
		fmt.Fprintf(os.Stderr, "Unable to read entry, %v", err)
		return err
	}

	//高等级日志亦落入低等级文件中
	for i := entry.Level; i <= entry.Logger.Level && i >= logrus.PanicLevel; i++ {
		_, err = hook.levelOutputs[i].Write([]byte(line))
		if err != nil {
			fmt.Fprintf(os.Stderr, "Unable to write entry, %v", err)
			return err
		}
	}

	return nil
}

func (hook *RotateHook) doRotate(level logrus.Level) {
	for i := int(level); i >= int(logrus.PanicLevel); i-- {
		err := hook.levelOutputs[i].Rotate()
		if err != nil {
			fmt.Fprintf(os.Stderr, "RotateHook doRotate error: %v", err)
		}
	}
}

func levelName(name string, levelText string) string {
	filename := filepath.Base(name)
	ext := filepath.Ext(filename)
	prefix := filename[:len(filename)-len(ext)]
	return fmt.Sprintf("%s.%s%s", prefix, levelText, ext)
}
